package com.intelligentmeterreadingsys.util;



import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * 系统和蓝牙设备交互的Service
 * 
 * @author MODUN
 * 
 */
public class BluetoothReaderCommunicationService {

	private static BluetoothReaderCommunicationService service;// 单例
	private static final String TAG = BluetoothReaderCommunicationService.class
			.getSimpleName();

	private static final UUID MY_UUID = UUID
			.fromString("00001101-0000-1000-8000-00805F9B34FB");// 唯一标识符

	private Handler mHandler;// 蓝牙消息接收器
	private ConnectClientModeThread mConnectClientModeThread;// 蓝牙客户端模式连接线程
	private ConnectedThread mConnectedThread;// 连接成功后监听线程
	private int mState = STATE_NONE;// 连接状态
	public static final int STATE_NONE = 0; // 没有连接
	public static final int STATE_CONNECTING = 1; // 正在连接
	public static final int STATE_CONNECTED = 2; // 已连接

	private BluetoothReaderCommunicationService() {
	}

	public static synchronized BluetoothReaderCommunicationService defaultService(
			Handler handler) {
		if (service == null) {
			service = new BluetoothReaderCommunicationService();
		}
		service.mHandler = handler;
		return service;
	}

	private void setState(int state) {
		mState = state;
		if (mHandler != null) {
			mHandler.obtainMessage(BluetoothHelp.MESSAGE_STATE_CHANGE,
					state, -1).sendToTarget();
		}
	}

	public int getState() {
		return mState;
	}

	public void connect(BluetoothDevice device) {
		disConnect();
		mConnectClientModeThread = new ConnectClientModeThread(device);
		mConnectClientModeThread.start();
	}

	
	public synchronized void connected(BluetoothSocket socket) {
		Log.i(TAG, "开启蓝牙连接");
		stopAllThread();
		mConnectedThread = new ConnectedThread(socket);
		mConnectedThread.start();
	}

	public void disConnect() {
		Log.i(TAG, "关闭蓝牙连接");
		stopAllThread();
		setState(STATE_NONE);
	}

	public void releaseHandler() {
		mHandler = null;
	}

	private void stopAllThread() {
		if (mConnectedThread != null) {
			mConnectedThread.cancel();
		}
		if (mConnectClientModeThread != null) {
			mConnectClientModeThread.cancel();
		}
	}

	public synchronized String write(byte[] out) {
		mConnectedThread.write(out);
		try {
			Thread.sleep(300);
		} catch (InterruptedException e) {
		}
		return mConnectedThread.getResponse();
	}

	public synchronized void writeWithOutResponse(byte[] out) {
		mConnectedThread.write(out);
		try {
			Thread.sleep(150);
		} catch (InterruptedException e) {
		}
	}

	private void connectionFailed() {
		setState(STATE_NONE);

		if (mHandler != null) {
			Message msg = mHandler
					.obtainMessage(BluetoothHelp.MESSAGE_DIALOG);
			Bundle bundle = new Bundle();
			bundle.putString(BluetoothHelp.DIALOG,
					"无法连接到读卡器，请确认读卡器是否打开");
			msg.setData(bundle);
			mHandler.sendMessage(msg);
		}
	}

	private void connectionLost() {
		setState(STATE_NONE);

		if (mHandler != null) {
			Message msg = mHandler
					.obtainMessage(BluetoothHelp.MESSAGE_DIALOG);
			Bundle bundle = new Bundle();
			bundle.putString(BluetoothHelp.DIALOG, "与读卡器的连接丢失，请重新连接");
			msg.setData(bundle);
			
			mHandler.sendMessage(msg);
		}
	}

	private class ConnectClientModeThread extends Thread {
		//蓝牙数据交换客户端
		private final BluetoothSocket mmSocket;

		public ConnectClientModeThread(BluetoothDevice device) {
			BluetoothSocket tmp = null;
			setState(STATE_CONNECTING);
			try {
				tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
			} catch (IOException e) {
				Log.e(TAG, "创建ConnectClientModeThread BluetoothSocket失败");
				connectionFailed();
			}
			mmSocket = tmp;
		}

		@Override
		public void run() {
			if (mmSocket != null) {
				try {
					mmSocket.connect();
				} catch (IOException e) {
					Log.e(TAG, "执行 ConnectClientModeThread  BluetoothSocket.connect()失败");
					cancel();
					connectionFailed();
					return;
				}
				mConnectClientModeThread = null;
				connected(mmSocket);
			}
		}

		public void cancel() {
			Log.i(TAG, "关闭蓝牙客户端模式数据通道");
			try {
				mmSocket.close();
			} catch (IOException e) {
			}
			mConnectClientModeThread = null;
		}
	}
	
	private class ConnectedThread extends Thread {
		private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        private final byte[]  buffer = new byte[1024];
		private byte[] mmRequest;
		private StringBuffer mmResponse;
		
		public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(TAG, "创建输入输出流失败");
                cancel();
                connectionFailed();
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            setState(STATE_CONNECTED);
        }

		public synchronized void write(byte[] request) {
			try {
				mmResponse = new StringBuffer();
				mmRequest = request;
				mmOutStream.write(mmRequest);

				if (mHandler != null) {
					mHandler.obtainMessage(BluetoothHelp.MESSAGE_WRITE,
							-1, -1,
							CHexConver.byte2HexStr(mmRequest, mmRequest.length))
							.sendToTarget();
				}
			} catch (IOException e) {
				cancel();
				connectionLost();
			}
		}

		@Override
		public void run() {
			try {
				while (true) {
					int bytes = mmInStream.read(buffer);
					mmResponse.append(" "
							+ CHexConver.byte2HexStr(buffer, bytes));
				}
			} catch (IOException e) {
				cancel();
				connectionLost();
			}
		}

		public synchronized String getResponse() {
			if (mHandler != null) {
				mHandler.obtainMessage(BluetoothHelp.MESSAGE_READ, -1,
						-1, mmResponse.toString().trim()).sendToTarget();
			}

			return mmResponse.toString().trim();
		}
		
		public synchronized void cancel() {
			Log.i(TAG, "关闭输入输出流通道");
            try {
                mmSocket.close();
            } catch (IOException e) {
            }
            mConnectedThread = null;
        }
	}
}
